﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Globalization;

namespace VKontakteClient
{
    class AudioSearcher:INotifyPropertyChanged
    {
        public class AudioContainer:INotifyPropertyChanged
        {
            private AudioSearcher _parent;
            public AudioContainer(GetAudioType Func, AudioSearcher Parent)
            {
                GetAudio = Func;
                _isVisible = true;
                _parent = Parent;
            }
            public delegate void GetAudioType();
            public GetAudioType GetAudio;
            private Audio _realAudio;
            public bool IsDownloaded
            {
                get
                {
                    return _realAudio != null;
                }
            }
            public Audio Audio
            {
                get
                {
                    if (_realAudio == null && GetAudio != null && IsVisible)
                    {
                        var a = GetAudio;
                        GetAudio = null;
                        App.Scheduler.Enqueue(
                        () =>
                        {
                            if (a != null)
                                a();
                        },ThreadPriority.Normal, () =>
                        {
                            return "Получение списка аудиозаписей по поиску...";
                        }, () =>
                        {
                            if (PropertyChanged != null)
                            {
                                PropertyChanged(this, new PropertyChangedEventArgs("Audio"));
                            }
                        });
                    }
                    return _realAudio;
                }
                set
                {
                    if (PropertyChanged != null)
                        PropertyChanged(this, new PropertyChangedEventArgs("Audio"));
                    _realAudio = value;
                }
            }
            private bool _isVisible;
            public bool IsVisible { 
                get
                {
                    return _isVisible;
                }
                set 
                {
                    _isVisible = value;
                    if (_parent != null)
                        _parent.AudioUpdated();
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
        }

        private void AudioUpdated()
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("NormalAudioList"));
                PropertyChanged(this, new PropertyChangedEventArgs("ClearAudioList"));
            }
        }
        private AudioContainer[] AudioList { get; set; }
        public IEnumerable<AudioContainer> ClearAudioList
        {
            get
            {
                List<AudioContainer> l = new List<AudioContainer>();
                foreach (var v in AudioList.Where(v=>v!=null&&v.IsDownloaded))
                {
                    if (!l.Any(q => q.Audio.Name.ToLower(CultureInfo.CurrentCulture) == v.Audio.Name.ToLower(CultureInfo.CurrentCulture) && q.Audio.MaximumProgress == v.Audio.MaximumProgress))
                    {
                        l.Add(v);
                    }
                }
                return l;
            }
        }
        public IEnumerable<AudioContainer> NormalAudioList
        {
            get
            {
                return AudioList.Where(v => v!=null && v.IsVisible == true);
            }
        }
        private int _audioFound = 0;
        private string _searchStr = "";
        private const string url = "audiosearch.php";
        public string StringToSearch
        {
            get;
            private set;
        }
        public void LoadAll()
        {
            foreach (var v in AudioList)
            {
                if (v.GetAudio != null)
                {
                    var a = v.GetAudio;
                    v.GetAudio = null;
                    App.Scheduler.Enqueue(
                    () =>
                    {
                        if (a != null)
                            a();
                    }, ThreadPriority.Normal, () =>
                    {
                        return "Получение списка аудиозаписей по поиску...";
                    }, () =>
                    {
                        AudioUpdated();
                    });
                }
            }
        }
        public AudioSearcher(string whatToSearch)
        {
            App.Scheduler.Enqueue(
                () =>
                {
                    StringToSearch = whatToSearch;
                    _searchStr =/*add=1&gid=0&to_id=0&*/ "q=" + System.Web.HttpUtility.UrlEncode(whatToSearch, System.Text.Encoding.GetEncoding(1251));
                    var text = VKontakteAPI.GetPage(url + "?" + _searchStr, 2);
                    try
                    {
                        var count = text.Remove(0, text.IndexOf("<div id=\"bigSummary\"", StringComparison.CurrentCulture));
                        count = count.Remove(0, count.IndexOf("<div class=\"summary\"", StringComparison.CurrentCulture));
                        count = count.Remove(0, count.IndexOf(">", StringComparison.CurrentCulture) + 1);
                        count = count.Remove(count.IndexOf("<", StringComparison.CurrentCulture));
                        if (count.StartsWith("Найдено",StringComparison.CurrentCulture))
                        {

                            count = count.Remove(0, count.IndexOf(" ", StringComparison.CurrentCulture) + 1);
                            count = count.Remove(count.IndexOf(" ", StringComparison.CurrentCulture));
                            _audioFound = int.Parse(count,CultureInfo.InvariantCulture);
                            AudioList = new AudioContainer[_audioFound];
                            object[] o = new object[(int)Math.Ceiling((double)_audioFound/100)];
                            for (int i = 0; i < o.Length; i++) o[i] = new object();
                            for (int a = 0; a < _audioFound; a++)
                            {
                                int i = a;
                                AudioList[i] = new AudioContainer(
                                    () =>
                                    {
                                        if (Monitor.TryEnter(o[(int)Math.Floor((double)i / 100)]))
                                        {
                                            int st = (int)Math.Floor((double)i / 100) * 100;
                                            if (st > 0) st--;
                                            if (AudioList[st].IsVisible==false || AudioList[st].Audio != null) return;
                                            string s = VKontakteAPI.GetPage(url + "?st=" + st + "&" + _searchStr, 0);
                                            var list = VKontakteAPI.ParseHTMLToAudio(s, false);
                                            for (int j = 0 + st; j < st + Math.Min(list.Count(), 100); j++)
                                                AudioList[j].Audio = list.ElementAt(j - st);
                                            for (int j = 0 + st + list.Count(); j < Math.Min(st + 100,AudioList.Length); j++)
                                                AudioList[j].IsVisible = false;
                                            AudioUpdated();
                                            Monitor.Exit(o[(int)Math.Floor((double)i / 100)]);
                                        }
                                    }, this);
                            }
                            var qq = VKontakteAPI.ParseHTMLToAudio(text, false);
                            for (int i = 0; i < qq.Count(); i++)
                            {
                                AudioList[i].Audio = qq.Skip(i).First();
                            }
                            AudioUpdated();
                        }
                        else
                        {
                            _audioFound = 0;
                        }
                    }                    
                    catch
                    {
                        _audioFound = 0;
                    }
                }, ThreadPriority.Normal, () =>
                { 
                    return "Поиск аудиозаписей..."; 
                });
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}
